package com.dx_society.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dx_society.domain.Societies;
import com.dx_society.domain.SocietiesMember;
import com.dx_society.domain.SocietyNotice;
import com.dx_society.domain.User;
import com.dx_society.dto.*;
import com.dx_society.mapper.SocietiesMemberMapper;
import com.dx_society.mapper.UserMapper;
import com.dx_society.service.SocietiesService;
import com.dx_society.mapper.SocietiesMapper;
import com.dx_society.service.SocietyNoticeService;
import com.dx_society.utils.UserHolder;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.dx_society.utils.RedisConstants.*;

/**
 * @author 韶光善良君
 * @description 针对表【dx_societies(社团表)】的数据库操作Service实现
 * @createDate 2024-07-01 10:15:21
 */
@Service
public class SocietiesServiceImpl extends ServiceImpl<SocietiesMapper, Societies>
        implements SocietiesService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedissonClient redissonClient;

    @Resource
    private SocietiesMemberMapper societiesMemberMapper;

    @Resource
    private UserMapper userMapper;
    @Resource
    private SocietyNoticeService societyNoticeService;

    @Override
    public Result querySocietiesList(String type, String name, Integer orderRole) {
        //1.从redis查询社团列表缓存
        List<String> listCache = stringRedisTemplate.opsForList().range(SOCIETIES_LIST_KEY, 0, -1);
        //2.判断是否为空
        if (listCache != null && !listCache.isEmpty()) {
            //不为空，返回列表
            List<Societies> societiesList = listCache.stream()
                    .map(str -> (Societies) JSONUtil.toBean(str, Societies.class, true))
                    .toList();
            if (type != null && !type.isEmpty()) {
                societiesList = societiesList.stream()
                        .filter(societies -> societies.getSoType().equals(type))
                        .collect(Collectors.toList());
            }
            if (name != null && !name.isEmpty()) {
                societiesList = societiesList.stream()
                        .filter(societies -> societies.getSoName().contains(name))
                        .collect(Collectors.toList());
            }
            if (societiesList.isEmpty()) {
                return Result.fail("没有找到符合条件的社团信息");
            }
            //排序方案 0默认排序 1参加人数降序 2参加人数升序 3名称排序升序 4名称排序降序
            switch (orderRole) {
                case 0:
                    societiesList = societiesList.stream().sorted(Comparator.comparingLong(Societies::getSoId)).toList();
                    break;
                case 1:
                    societiesList = societiesList.stream().sorted(Comparator.comparingLong(Societies::getSoCount).reversed()).toList();
                    break;
                case 2:
                    societiesList = societiesList.stream().sorted(Comparator.comparingLong(Societies::getSoCount)).toList();
                    break;
                case 3:
                    societiesList = societiesList.stream().sorted((l1, l2) -> {
                        Collator instance = Collator.getInstance(Locale.CHINA);
                        return instance.compare(l1.getSoName(), l2.getSoName());
                    }).toList();
                    break;
                case 4:
                    societiesList = societiesList.stream().sorted((l1, l2) -> {
                        Collator instance = Collator.getInstance(Locale.CHINA);
                        return -instance.compare(l1.getSoName(), l2.getSoName());
                    }).toList();
                    break;
            }
            return Result.ok(societiesList);
        }
        // 缓存不存在则重建缓存
        saveSocieties2Redis(SOCIETIES_LIST_TTL);
        return querySocietiesList(type, name, orderRole);
    }

    @Override
    public void saveSocieties2Redis(Long expireSeconds) {
        // 添加分布式锁
        RLock lock = redissonClient.getLock(CACHE_SO_LOCK_KEY);
        boolean isLock = lock.tryLock();
        if (isLock) {
            try {
                List<Societies> societiesList = list();
                // 检查数据库缓存是否存在，存在则删除缓存
                if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(SOCIETIES_LIST_KEY))) {
                    stringRedisTemplate.delete(SOCIETIES_LIST_KEY);
                }
                // 将数据写入redis
                List<String> strList = societiesList.stream().map(JSONUtil::toJsonStr).collect(Collectors.toList());
                stringRedisTemplate.opsForList().rightPushAll(SOCIETIES_LIST_KEY, strList);
                stringRedisTemplate.expire(SOCIETIES_LIST_KEY, expireSeconds, TimeUnit.MINUTES);
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                //释放锁
                lock.unlock();
            }
        }
    }

    @Override
    public Result querySocietiesDetail(Long id) {
        Long userId;
        try {
            userId = UserHolder.getUser().getUserid();
        } catch (Exception e) {
            return Result.fail("用户未登录");
        }
        //1.从redis查询社团列表缓存
        List<String> listCache = stringRedisTemplate.opsForList().range(SOCIETIES_LIST_KEY, 0, -1);
        //2.判断是否为空
        if (listCache != null && !listCache.isEmpty()) {
            Societies society = listCache.stream()
                    .map(str -> (Societies) JSONUtil.toBean(str, Societies.class, true))
                    .filter(societies -> societies.getSoId().equals(id))
                    .findFirst().orElse(null);
            if (society == null) {
                return Result.fail("没有找到该社团信息");
            }
            SoDetailDTO soDetailDTO = new SoDetailDTO();
            soDetailDTO.setSocieties(society);
            QueryWrapper<SocietiesMember> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("societies_id", id);
            queryWrapper.eq("user_id", userId);
            SocietiesMember societiesMember = societiesMemberMapper.selectOne(queryWrapper);
            // 检查是否存在
            if (societiesMember != null) {
                soDetailDTO.setIsMember(societiesMember.getState());
            } else {
                // 不是该部部员
                soDetailDTO.setIsMember(-1);
            }
            return Result.ok(soDetailDTO);
        }
        // 缓存不存在则重建缓存
        saveSocieties2Redis(SOCIETIES_LIST_TTL);
        return querySocietiesDetail(id);
    }

    @Override
    public Result querySocietiesDetailByMasterId() {
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return Result.fail("请先登录");
        } else if (user.getRole() != 1) {
            return Result.fail("权限不足");
        }
        Societies soMasterId = query().eq("so_master_id", user.getUserid()).one();
        return Result.ok(soMasterId);
    }

    @Override
    public Result updateSocieties(SoMDTO soMDTO) {
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return Result.fail("请先登录");
        } else if (user.getRole() != 1) {
            return Result.fail("权限不足");
        }
        Societies soMasterId = query().eq("so_master_id", user.getUserid()).one();
        soMasterId.setSoDetail(soMDTO.getSoDetail());
        soMasterId.setSoTeacherName(soMDTO.getSoTeacherName());
        if (saveOrUpdate(soMasterId)) {
            return Result.ok("修改信息成功");
        }
        return Result.fail("修改信息失败");
    }

    @Override
    public Result changeMySociety(Long newUserId) {
        // 1.校验身份
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return Result.fail("请先登录");
        } else if (user.getRole() != 1) {
            return Result.fail("权限不足");
        }
        User user1 = userMapper.selectById(newUserId);
        if (user1 == null) {
            return Result.fail("目标用户不存在");
        }
        if (user1.getRole() != 2) {
            return Result.fail("目标用户已有身份定义");
        }
        // 2.将社团的管理者id和名称修改
        Societies soMasterId = query().eq("so_master_id", user.getUserid()).one();
        soMasterId.setSoMasterId(newUserId);
        soMasterId.setSoMasterName(user1.getUsername());
        // 3.用户的身份修改
        User user2 = new User();
        user2.setUserid(user.getUserid());
        user2.setRole(2);
        user1.setRole(1);

        if (userMapper.updateById(user1) == 1 && userMapper.updateById(user2) == 1 && saveOrUpdate(soMasterId)) {
            return Result.ok("修改成功");
        }
        return Result.fail("修改失败");
    }

    @Override
    public Result querySocietyNotice(Long id) {
        Long userId;
        try {
            userId = UserHolder.getUser().getUserid();
        } catch (Exception e) {
            return Result.fail("用户未登录");
        }
        QueryWrapper<SocietiesMember> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("societies_id", id);
        queryWrapper.eq("user_id", userId);
        SocietiesMember societiesMember = societiesMemberMapper.selectOne(queryWrapper);
        // 检查是否存在
        if (societiesMember != null) {
            List<SocietyNotice> soId = societyNoticeService.query().eq("so_id", id).list();
            return Result.ok(soId);
        } else {
            return Result.fail("您未加入该社团");
        }
    }

    @Override
    public Result querySocietyBrief() {
        //1.从redis查询社团列表缓存
        List<String> listCache = stringRedisTemplate.opsForList().range(SOCIETIES_LIST_KEY, 0, -1);
        //2.判断是否为空
        if (listCache != null && !listCache.isEmpty()) {
            //不为空，返回列表
            List<Societies> societiesList = listCache.stream()
                    .map(str -> (Societies) JSONUtil.toBean(str, Societies.class, true))
                    .toList();
            List<SoDTO> soDTOList = new ArrayList<>();
            for (Societies societies : societiesList) {
                SoDTO soDTO = BeanUtil.copyProperties(societies, SoDTO.class);
                soDTOList.add(soDTO);
            }
            return Result.ok(soDTOList);
        }
        // 缓存不存在则重建缓存
        saveSocieties2Redis(SOCIETIES_LIST_TTL);
        return querySocietyBrief();
    }


}




